/*
	MIDAS Context Based Routing
	cbr_msgcache.h
	Copyright (c) 2007 Radoslaw Olgierd Schoeneich
	MEAG IT PW
 */

#ifndef cbr_msgcache_h_
#define cbr_msgcache_h_

#include <list>
#include <stdio.h>

#include <semaphore.h>

#include "packet.h"

#include "cbr_packet.h"
#include "cbr_address.h"

class cbr_Msg : public cbr_Object {
public:
	enum state_t {
		RREQ,		// waiting for RREP
		SENT,		// at least one chunk sent
		INCOMPLETE,	// waiting for next chunks
		COMPLETE,	// received entire message
		OTHER
	};

private:
	int32_t			total;
	int32_t			length;
	char*			payload;
	state_t			state;

	bool			mcast;
	cbr_ContextAddress*	addr;
	u_int32_t		transactionID;

	double			expire;

public:
	cbr_Msg(int32_t total, int32_t length, const char* payload,
		const cbr_ContextAddress* addr, u_int32_t tid,
		state_t state, double expire);

	~cbr_Msg();

	int32_t		getTotalLength() const { return total; }
	int32_t		getCurrentLength() const { return length; }
	int32_t		getPayload(char* dest, int32_t offset, int32_t len);

	state_t		getState() const { return state; }
	void		setState(state_t state)
	{
		this->state = state;
		if (state == COMPLETE)
			this->total = this->length;
	}

	bool		isMulticast() const { return this->mcast; }
	void		setMulticast(bool m = true) { this->mcast = m; }

	cbr_ContextAddress* getAddress() const { return addr; }
	u_int32_t	getTransactionID() const { return transactionID; }

	double		expires() const { return expire; }

	state_t		add(const char* data, int32_t offset, int32_t len);
};

class cbr_MsgCache : public cbr_Object {
private:
	sem_t msgcache_sem;
	typedef std::list<cbr_Msg*> msgs_list;
	msgs_list queue;
	int count;

public:
	cbr_MsgCache();
	~cbr_MsgCache();

        void		enqueue(cbr_Msg *msg);
        cbr_Msg*	lookup(u_int32_t tid, bool dequeue = false);
	void		purge();
};

#endif	// cbr_msgcache_h_
